package nsalt

import chisel3._
import chisel3.util._

class FeedbackPort extends Bundle with Config {

  val valid = Output(Bool())

  val pc           = Output(UInt(VIRT_MEM_ADDR_LEN.W))
  val isMispred    = Output(Bool())
  val branchDest   = Output(UInt(VIRT_MEM_ADDR_LEN.W))
  val operType     = Output(OperType())
  val branchType   = Output(BranchType())
  val branchTaken  = Output(Bool())  // for branch
  
  val compressed   = Output(Bool())  // for ras, save PC+2 to stack if is RVC
}

class PredictPort extends Bundle {
  val flush = Input(Bool())
  val feed  = Flipped(new FeedbackPort())
  val pc    = Flipped(Valid(UInt(32.W)))
}


class CtrlFlowPort extends Bundle with Config {

  val instr  = Output(UInt(DATA_BITS.W))
  val pc     = Output(UInt(VIRT_MEM_ADDR_LEN.W))
  val pcPred = Output(UInt(VIRT_MEM_ADDR_LEN.W))
  
  val redirect = new RedirectPort()
  
  // N/A for this moment
  val exceptionVec = Output(Vec(16, Bool()))
  val intrVec = Output(Vec(12, Bool()))
  val branchIndex = Output(UInt(4.W))
  val isRVC = Output(Bool())
  val crossPageIPFFix = Output(Bool())
}

class RedirectPort extends Bundle with Config {
  val valid = Output(Bool())
  
  val dest = Output(UInt(VIRT_MEM_ADDR_LEN.W))
  
  // 1: branch mispredict: only need to flush frontend
  // 0: others: flush the whole pipeline
  val wholeFlushed = Output(UInt(1.W))
}


class MemManagePort extends Bundle with Config {

  val priviledgeMode = Input(UInt(2.W))
  val statusSUM = Input(Bool())
  val statusMXR = Input(Bool())

  val loadPageFault = Output(Bool())
  val storePageFault = Output(Bool())
  val addr = Output(UInt(VIRT_MEM_ADDR_LEN.W)) 
  
  def isPageFault() = loadPageFault || storePageFault
  
} 


class MemUniPort extends Bundle with Config {
  val imem = new MemManagePort
  val dmem = new MemManagePort
}


class WriteRegFilePort extends Bundle with Config {
  val enableW = Output(Bool())
  val dest = Output(UInt(5.W))
  val data = Output(UInt(XLEN.W))
}

class ForwardPort extends Bundle with Config {
  val valid = Output(Bool())
  val writeReg = new WriteRegFilePort
  val funcType = Output(FuncType())
}
